package com.ebc.eservice.service.app.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ebc.eservice.mapper.*;
import com.ebc.eservice.pojo.*;
import com.ebc.eservice.service.app.AppLoginService;
import com.ebc.eservice.service.app.PersonCardService;
import com.ebc.eservice.service.cardStat.CardStatImp;
import com.ebc.eservice.util.JsonResult;
import com.ebc.eservice.util.JwtUtil;
import com.ebc.eservice.util.MyTimeUtil;
import com.ebc.eservice.vo.card.CardInfoVo;
import com.ebc.eservice.vo.user.LoginUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HyperLogLogOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author: Joey
 * @Description:app端业务
 * @date:2022/9/23 23:06
 */
@Service
@Slf4j
public class LoginAppImp implements AppLoginService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private EbcCardStatMapper ebcCardStatMapper;
    @Autowired
    private InteractClientMapper clientMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private CompanyMapper companyMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult appLogin(LoginUserVo emp) {

        // 在没认证之前principal, credentials两个参数分别存放用户名和密码
        UsernamePasswordAuthenticationToken authenticationToken2 =
                new UsernamePasswordAuthenticationToken(emp.getUserAccount(),emp.getPassword());
        // 通过AuthenticationManager的authenticate方法来进行用户认证 loadUserByUsername()的返回值
        Authentication authenticate = authenticationManager.authenticate(authenticationToken2);
        // 判断是否验证成功
        if(Objects.isNull(authenticate)){
            return JsonResult.fail("用户不存在");
//            throw new RuntimeException("用户名或密码错误");
        }
        // 在认证信息authenticate中获取登录成功后的用户信息
        UserDT user = (UserDT) authenticate.getPrincipal();
        System.out.println(user);
        // 使用userid生成token
        String userId = user.getUser().getId().toString();
        HashMap<String,Object> map = new HashMap<>();
        List<EbcRole> roles = roleMapper.getUserRolesByUid(Integer.parseInt(userId));

        //判定权限 用户和员工进入
        if(roles.get(0).getRoleCode().contains("v2") || roles.get(0).getRoleCode().contains("c1")){
            user.setPermissions(roles.get(0).getRoleCode());
            String jwt = JwtUtil.createJWT(userId);

            CardInfoVo card = new CardInfoVo();
//            CardInfoVo ebcCard = new CardInfoVo();
            if(roles.get(0).getRoleCode().contains("v2")){
                card = cardMapper.getPersonCard(Integer.parseInt(userId));
                System.out.println("==========================员工进入==============================");
            }else{
                card = cardMapper.getCardById(emp.getCardId());
                if(card==null){
                    return JsonResult.fail("当前无名片展示");
                }
                addVisitNum(card.getCardId(),Integer.parseInt(userId));
                //todo 计算时间
                long start = System.currentTimeMillis();
                redisTemplate.opsForValue().set("staytime:"+userId,start,60, TimeUnit.MINUTES);
                System.out.println("===============================用户进入=========================");
            }
            map.put("cardInfo",card);
            map.put("token",jwt);
            map.put("user",user);
            // userId用作key，将用户信息存入redis，并设置时间过期
            redisTemplate.opsForValue().set("tk" + userId, user,20, TimeUnit.MINUTES);
            return JsonResult.success(map);
        }else{
           return JsonResult.fail("账号权限不匹配,请重新输入");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public JsonResult logout(Integer cardId){//Integer cardId
        EbcUser loginUser = (EbcUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        EbcCard card = cardMapper.selectById(cardId);
        JsonResult result=null;
        if(card.getUserId() == loginUser.getId()){//员工退出
            log.info("员工账号退出 ID:"+loginUser.getId());
            redisTemplate.delete("tk"+loginUser.getId());
        }else{
            int minutes=0;
            long startTime=0;
            int time = timeLenth(loginUser.getId());
            if(loginUser == null){
                return JsonResult.fail("注销失败");
            }else{
                System.out.println("注销用户: "+loginUser);
                int userid = loginUser.getId();
                addStayTimes(cardId ,loginUser.getId());
                redisTemplate.delete("tk"+userid);
            }
            log.info("用户:"+loginUser.getId()+"退出,在线时长: "+time+"分钟");
        }

        return JsonResult.success("注销成功");
    }

    //todo  计算用户在线时长，需要用户在线时记录

    //增加时长记录
    public void addStayTimes(int cardId ,int userId){
        MyTimeUtil timeUtil = new MyTimeUtil();
        String today = timeUtil.getToDay();
        int time = timeLenth(userId);
        redisTemplate.opsForHash().increment("card:"+cardId+":date:"+today,
                "stayNum", time);
        QueryWrapper<EbcCardStat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("date_flag",today);
        queryWrapper.eq("card_id",cardId);
        EbcCardStat cardStat = ebcCardStatMapper.selectOne(queryWrapper);
        if(cardStat == null){
            EbcCardStat stat = new EbcCardStat();
            stat.setCardId(cardId).setStayTimes(time)
                    .setCreateStatTime(new Date()).setDateFlag(today)
                    .setDownloadNum(0).setAddContactNum(0)
                    .setStayTimes(0).setMessageNum(0).setForwardNum(0).setCopyWxAccount(0);
            ebcCardStatMapper.insert(stat);
        }else{  //不为空则更新+1
//            time = timeLenth(userId);
            ebcCardStatMapper.addStayTime(time,today);
        }
    }

    //时长计算  注销redis该用户计时
    public int timeLenth(int userId){
        long endTime = System.currentTimeMillis();
        long startTime = (long) redisTemplate.opsForValue().get("staytime:" + userId);
        int hours=(int) ((endTime-startTime)/(1000*60*60));//小时
        int minutes=(int) (((endTime-startTime)/1000-hours*(60*60))/60);//分钟

        redisTemplate.delete("staytime:"+userId);
        if(minutes == 0){
            minutes = 0;
        }
        return minutes;
    }

    //增加访客记录  名片+客户交互
    @Transactional(rollbackFor = Exception.class)
    public void addVisitNum(int cardId , int userId){
        MyTimeUtil timeUtil = new MyTimeUtil();
        String today = timeUtil.getToDay();
        //redis 名片访客 +1                      格式： card:1:date:09-20,< visit ,1 >
        redisTemplate.opsForHash().increment("card:"+cardId+":date:"+today,
                "visit", 1);
        //redis  客户数量记录+1 自动去重
        HyperLogLogOperations<String, String> clientVo = redisTemplate.opsForHyperLogLog();
        clientVo.add("cardclient:"+cardId+":date:"+today,"user:"+userId);

        //名片
        QueryWrapper<EbcCardStat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("date_flag",today);
        queryWrapper.eq("card_id",cardId);
        EbcCardStat cardStat = ebcCardStatMapper.selectOne(queryWrapper);
        if(cardStat == null){
            EbcCardStat stat = new EbcCardStat();
            stat.setCardId(cardId)
                    .setVisitNum(1)
                    .setCreateStatTime(new Date()).setDateFlag(today)
                    .setDownloadNum(0).setAddContactNum(0)
                    .setStayTimes(0).setMessageNum(0).setForwardNum(0).setCopyWxAccount(0);
            ebcCardStatMapper.insert(stat);
        }else{  //不为空则更新+1
            ebcCardStatMapper.addVisit(today);
        }
        //客户
        QueryWrapper<EbcInteractClient> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("create_inter_time",today);
        queryWrapper2.eq("user_id",userId);
        queryWrapper2.eq("card_id",cardId);
        EbcInteractClient selectClient = clientMapper.selectOne(queryWrapper2);
        if(selectClient == null){//客户第一次访问
            EbcInteractClient client = new EbcInteractClient();
            client.setCardId(cardId).setUserId(userId).setCreateInterTime(today).setInteractNum(1);
            clientMapper.insert(client);
        }else{ //不为空则更新+1
            clientMapper.updateInteractNum(today,userId);
        }
    }

//    public EbcCompany getComapny(Integer cardId){
//        EbcCompany company = companyMapper.selectById(cardId);
//        return company;
//    }

}
